package commands;

import java.util.Calendar;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import modLoader.ModLoader;

import bot.CommandBot;
import cmdclasses.timer.TimerRunnableImpl;

import com.mdimension.jchronic.Chronic;
import com.mdimension.jchronic.Options;
import com.mdimension.jchronic.utils.Span;

public class Timer implements Command {

	HashMap<String, Binder> timers;

	@Override
	public String getCommandName() {
		return "timer";
	}

	public Timer() {
		timers = new HashMap<String, Binder>();
	}

	@Override
	public boolean execCommand(String channel, String sender, String login,
			String hostname, String message, CommandBot bot) {
		return fixTimer(channel, sender, message, bot);

	}

	@Override
	public boolean execCommand(String sender, String login, String hostname,
			String message, CommandBot bot) {
		return fixTimer(sender, sender, message, bot);
	}

	private boolean fixTimer(String channel, String sender, String message,
			CommandBot bot) {
		if (message.equals("")) {
			showTimer(channel, sender, bot);
			return true;
		} else if (message.startsWith(" at ")) {
			atTimer(channel, sender, message, bot);
			return true;
		} else if (message.startsWith(" in ")) {
			inTimer(channel, sender, message, bot);
			return true;
		} else if(message.equals("stop")) {
			Binder binder =timers.remove(sender);
			if(binder != null) {
			binder.getTimer().cancel();
			bot.sendMessage(channel, "Timer stopped", true);
			}
			return true;
		}
		return false;
	}

	private void inTimer(final String channel, final String sender,
			String message, final CommandBot bot) {
		try {
			Calendar d = parseInDate(message);
			if(createTimer(channel, sender, bot, d)){
				bot.sendMessage(channel, "Timer has been set at " + d.getTime(), true);
			}
		} catch (Exception e) {
			bot.sendMessage(channel, e.getMessage(), true);
		}
	}

	private void atTimer(String channel, String sender, String message,
			CommandBot bot) {
		try {
			Calendar d = parseAtDate(message);
			if(createTimer(channel, sender, bot, d)){
				bot.sendMessage(channel, "Timer has been set at " + d.getTime(), true);
			}
		} catch (Exception e) {
			bot.sendMessage(channel, e.toString(), true);
		}
	}

	private void showTimer(String channel, String sender, CommandBot bot) {
		String time = timers.get(sender).getTime();
		String sendMessage = time;
		if (time == null) {
			sendMessage = "No timer has been set";
		} else {
			sendMessage = "Timer set at " + time;
		}
		bot.sendMessage(channel, sendMessage, true);
	}

	private Calendar parseAtDate(String message) {
		Span s = parseDate(message);
		return s.getEndCalendar();
	}

	private Calendar parseInDate(String message) {
		Calendar now = Calendar.getInstance();

		String time = message.substring(4).toLowerCase().trim();
		Pattern p = Pattern.compile("(([0-9]+h[ ]*)?([0-9]+m[ ]*)?([0-9]+s)?)");

		Matcher m = p.matcher(time);
		if (m.matches()) {
			String rest = addTime(now, Calendar.HOUR_OF_DAY, time, "h");
			rest = addTime(now, Calendar.MINUTE, rest, "m");
			rest = addTime(now, Calendar.SECOND, rest, "s");
		}
		return now;
	}

	private String addTime(Calendar cal, int field, String timeToSplit,
			String split) {
		String[] temp = timeToSplit.trim().split(split, 2);
		if (temp.length > 1) {
			int time = Integer.parseInt(temp[0]);
			cal.add(field, time);
		}
		return temp[temp.length - 1];
	}

	private Span parseDate(String message) {
		String time = message.substring(4);
		Options options = new Options();
		Span s = Chronic.parse(time, options);
		return s;
	}

	private synchronized boolean createTimer(final String channel, final String sender,
			final CommandBot bot, final Calendar time) {
		
		if (!timers.containsKey(sender)) {
			TimerRunnableImpl timer = (TimerRunnableImpl) ModLoader
					.newInstance("cmdclasses.timer.TimerRunnable");
			timer.setUp((CommandBot)bot, time, sender, channel, timers);
			java.util.Timer t = new java.util.Timer();
			long toSleep = time.getTimeInMillis()
					- Calendar.getInstance().getTimeInMillis();
			if (toSleep > 0) {
			t.schedule(timer, toSleep);
			timers.put(sender, new Binder(time,t));
			}
			return true;
		} else {
			bot.sendMessage(channel, "There has been set a timer already", true);
			return false;
		}
	}
	
	public class Binder {
		private Calendar time;
		private java.util.Timer timer;
		
		public Binder(Calendar time, java.util.Timer timer) {
			this.time = time;
			this.timer = timer;
		}

		public java.util.Timer getTimer() {
			return timer;
			
		}

		public String getTime() {
			return time.getTime().toString();
		}
	}
}
